using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace EasyShare
{
    public partial class ManageContactsForm : Form
    {
        #region Private Instance Members

        private ContactManager m_objContactManager = null;  // contact manager for operations on database

        #endregion

        #region Constructor

        public ManageContactsForm(ContactManager contactManager)
        {
            InitializeComponent();

            m_objContactManager = contactManager;
        }

        #endregion
        
        #region Private Helper Methods

        private void LoadContacts()
        {
            // Loading the contacts from the database
            // and binding to the datagrid
            DataTable contactsTable = null;
            bool ret = m_objContactManager.GetAllContacts(ref contactsTable);
            if (ret == true)
            {
                ManageContactsDataGridView.Rows.Clear();
                for (int i = 0; i < contactsTable.Rows.Count; i++)
                {
                    int index = ManageContactsDataGridView.Rows.Add();
                    ManageContactsDataGridView.Rows[index].Cells["SlNoColumn"].Value = (i + 1).ToString();
                    ManageContactsDataGridView.Rows[index].Cells["NameColumn"].Value = contactsTable.Rows[i]["Name"];
                    ManageContactsDataGridView.Rows[index].Cells["AliasColumn"].Value = contactsTable.Rows[i]["Alias"];
                }
            }
            else
            {
                MessageBox.Show("Error in reading contacts from the database", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                // this.Close();
            }
        }

        // sets error text for invalid users
        // among set of selected users
        private void SetErrorTextForInvalidUsers(List<string> contactsList, string[] invalidUsers)
        {
            // Building hashtable of selected users
            Dictionary<string, bool> userMap = new Dictionary<string, bool>();
            foreach (string userName in contactsList)
            {
                userMap.Add(userName, true);
            }
            for (int i = 0; i < invalidUsers.Length; i++)
            {
                if (userMap.ContainsKey(invalidUsers[i]) == true)
                {
                    userMap[invalidUsers[i]] = false; // setting false for invalid users
                }
            }

            // setting error text by searching the user map
            foreach (DataGridViewRow contactRow in ManageContactsDataGridView.SelectedRows)
            {
                string userName = contactRow.Cells["NameColumn"].Value.ToString().Trim();
                if (userMap.ContainsKey(userName) == true)
                {
                    if (userMap[userName] == false)
                    {
                        contactRow.ErrorText = "'" + userName + "' not found";
                    }
                    else
                    {
                        contactRow.ErrorText = string.Empty;
                    }
                }
            }
        }

        // fills the FullName column of the grid
        // with full names retrieved from validity check
        private void SetFullNameForValidUsers(Dictionary<string, string> userMap)
        {
            // setting error text by searching the user map
            foreach (DataGridViewRow contactRow in ManageContactsDataGridView.SelectedRows)
            {
                string userName = contactRow.Cells["NameColumn"].Value.ToString().Trim();
                if (userMap.ContainsKey(userName) == true)
                {
                    if (userMap.ContainsKey(userName) == true)
                    {
                        contactRow.Cells["FullNameColumn"].Value = userMap[userName];
                    }
                }
            }
        }

        private void DeleteSelectedContacts()
        {
            if (ManageContactsDataGridView.SelectedRows.Count == 0)
            {
                MessageBox.Show("Please select rows to be deleted", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List<string> contactsList = new List<string>();
            foreach (DataGridViewRow contactRow in ManageContactsDataGridView.SelectedRows)
            {
                contactsList.Add(contactRow.Cells["NameColumn"].Value.ToString());
            }

            // Show warning
            DialogResult dr = MessageBox.Show("Are you sure that you want to delete the " + contactsList.Count + " selected contact(s)?",
                EasyShareConstants.TOOL_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == DialogResult.Yes)
            {
                if (m_objContactManager.DeleteContacts(contactsList.ToArray()) == true)
                {
                    LoadContacts(); // reload the contacts grid
                }
                else
                {
                    MessageBox.Show("Error in deleting contacts from the database", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }        

        #endregion
        
        private void ManageContactsForm_Load(object sender, EventArgs e)
        {
            LoadContacts();
        }        

        // Displays form for adding a new contact
        // Reloads the contact grid if the addition is successful
        private void AddButton_Click(object sender, EventArgs e)
        {
            ContactForm contactForm = new ContactForm(m_objContactManager);
            DialogResult dr = contactForm.ShowDialog();

            if (dr == DialogResult.OK)
            {
                LoadContacts(); // Reload contacts grid
            }
        }

        // Displays form for editing a contact
        // Reloads the contact grid if the addition is successful
        private void EditButton_Click(object sender, EventArgs e)
        {
            if (ManageContactsDataGridView.SelectedRows.Count == 1) // check if exactly one row is selected
            {
                ContactForm contactForm = new ContactForm(m_objContactManager, ManageContactsDataGridView.SelectedRows[0].Cells["NameColumn"].Value.ToString(),
                    ManageContactsDataGridView.SelectedRows[0].Cells["AliasColumn"].Value.ToString());
                DialogResult dr = contactForm.ShowDialog();

                if (dr == DialogResult.OK)
                {
                    LoadContacts(); // Reload contacts grid
                }
            }
            else if (ManageContactsDataGridView.SelectedRows.Count == 0)
            {
                MessageBox.Show("Please select a row to edit", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                MessageBox.Show("Please select only one row to edit", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // Removes selected contacts from the database
        private void RemoveButton_Click(object sender, EventArgs e)
        {
            DeleteSelectedContacts();
        }

        // Key down event handler for the DataGridView
        private void ManageContactsDataGridView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                // Removes selected contacts from the database
                DeleteSelectedContacts();
            }            
        }

        // checks if the selected contact names are valid
        private void CheckButton_Click(object sender, EventArgs e)
        {
            if (ManageContactsDataGridView.SelectedRows.Count == 0)
            {
                MessageBox.Show("Please select rows to be checked", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List<string> contactsList = new List<string>();
            foreach (DataGridViewRow contactRow in ManageContactsDataGridView.SelectedRows)
            {
                contactsList.Add(contactRow.Cells["NameColumn"].Value.ToString());
            }

            // Checking validity asynchronously
            // this is necessary because wmi query for users
            // is a costly operation
            EasyShareConstants.Func<string[], string[], Dictionary<string, string>, bool> validationDelegate = new EasyShareConstants.Func<string[], string[], Dictionary<string, string>, bool>(Win32ShareWrapper.GetInvalidUsers);
            string[] invalidUsers = null;
            Dictionary<string, string> userMap = null;
            IAsyncResult token = validationDelegate.BeginInvoke(contactsList.ToArray(), ref invalidUsers, ref userMap, null, null);

            // Displaying the wait form
            WaitForm objWaitForm = new WaitForm(token, "Operation in Progress", "Searching for users..");
            objWaitForm.ShowDialog();

            // retrieving the result
            bool ret = validationDelegate.EndInvoke(ref invalidUsers, ref userMap, token);

            if (ret == true)
            {
                SetFullNameForValidUsers(userMap);

                if (invalidUsers.Length > 0)
                {
                    StringBuilder invalidUsersString = new StringBuilder();
                    for (int i = 0; i < invalidUsers.Length; i++)
                    {
                        invalidUsersString.Append(invalidUsers[i]);
                        invalidUsersString.Append(',');
                    }
                    if (invalidUsersString.Length > 0)
                    {
                        invalidUsersString.Remove(invalidUsersString.Length - 1, 1);
                    }

                    // Setting error text for the datagrid rows
                    SetErrorTextForInvalidUsers(contactsList, invalidUsers);

                    MessageBox.Show("Users name(s) - (" + invalidUsersString.ToString() + ") among the selected users were not found." + Environment.NewLine + Environment.NewLine 
                        + " Please enter usernames in the format '<domain_name>\\<user_name>'", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);                    
                }
                else
                {                    
                    MessageBox.Show("All selected user names are valid", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show("Error in searching for user names", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }        

        private void ManageContactsForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                // close the form if escape key is presed
                this.Close();
                e.Handled = true;
            }
        }             
    }
}